﻿using ChiWalker.Settings;
using ChiWalker.Spell;
using Styx;
using Styx.Pathing;
using Styx.TreeSharp;

namespace ChiWalker.Helpers
{
    public delegate WoWPoint LocationRetriever(object context);

    public delegate float DynamicRangeRetriever(object context);

    public class Movement
    {
        public static Composite FaceMyTarget()
        {
            return FaceUnit(ret => StyxWoW.Me.CurrentTarget);
        }

        public static Composite FaceUnit(UnitSelectionDelegate unit)
        {
            return
                new Decorator(
                    ctx =>
                        !ChiWalkerSettings.Instance.DisableMovement && unit != null && unit(ctx).InLineOfSight &&
                        !StyxWoW.Me.IsSafelyFacing(unit(ctx), 70f),
                    new Action(ctx => StyxWoW.Me.SetFacing(unit(ctx))));
        }

        public static Composite StopMoving()
        {
            return new Decorator(ret => !ChiWalkerSettings.Instance.DisableMovement && StyxWoW.Me.IsMoving,
                new Action(ret => Navigator.PlayerMover.MoveStop()));
        }

        public static Composite MoveToLoS(UnitSelectionDelegate unit)
        {
            return
                new Decorator(
                    ret =>
                        !ChiWalkerSettings.Instance.DisableMovement && unit(ret) != null &&
                        (!unit(ret).InLineOfSight || !unit(ret).InLineOfSpellSight),
                    CreateMoveToLocation(ret => unit(ret).Location));
        }

        public static Composite MoveToUnit(UnitSelectionDelegate unit)
        {
            return MoveToUnit(unit, ret => unit(ret).CombatReach + StyxWoW.Me.CombatReach + 1.33f);
        }

        public static Composite MoveToUnit(UnitSelectionDelegate unit, DynamicRangeRetriever range)
        {
            return CreateMoveToLocation(ret => unit(ret).Location, range);
        }

        public static Composite CreateMoveToLocation(LocationRetriever location)
        {
            return CreateMoveToLocation(location, ret => 1f);
        }

        public static Composite CreateMoveToLocation(LocationRetriever location, DynamicRangeRetriever range)
        {
            return
                new PrioritySelector(
                    new Decorator(
                        ret =>
                            !ChiWalkerSettings.Instance.DisableMovement &&
                            StyxWoW.Me.Location.Distance(location(ret)) <= range(ret),
                        StopMoving()),
                    new Decorator(
                        ret =>
                            !ChiWalkerSettings.Instance.DisableMovement &&
                            StyxWoW.Me.Location.Distance(location(ret)) >= range(ret),
                        new Action(ret => Navigator.MoveTo(location(ret)))));
        }
    }
}